package main

import (
	"database/sql"
	"fmt"
	"html/template"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"time"

	"git.oschina.net/goxiang2/web/admin/models"
	_ "git.oschina.net/goxiang2/web/admin/routers"
	"github.com/astaxie/beego"
	"github.com/astaxie/beego/orm"
	_ "github.com/go-sql-driver/mysql"
	_ "github.com/mattn/go-sqlite3"
	"github.com/yosssi/ace"
)

var dsn = "./admin.db"

func init() {
	//会话保存到文件中
	beego.BConfig.WebConfig.Session.SessionOn = true
	// beego.BConfig.WebConfig.Session.SessionName = "*controllers.LoginInfo"
	// beego.BConfig.WebConfig.Session.SessionProvider = "file"
	// beego.BConfig.WebConfig.Session.SessionProviderConfig = "./session"
	// session.Register(name, provide)
}

func addAceTemplate() {
	funcMap := template.FuncMap{
		"GetRoleById": func(id int64) string {
			role := models.GetRoleById(id)
			if role == nil {
				return ""
			}
			return role.Name
		},
		"TimeToStr": func(i int64) string {
			return time.Unix(int64(i), 0).Format("2006-01-02 15:04:05")
		},
		"FeedbackToStr": func(i int) string {
			if i == 2 {
				return "已回复"
			} else {
				return "未回复"
			}
		},
		"ClientTypeToStr": func(i int64) string {
			if i == 1 {
				return "安卓"
			} else if i == 2 {
				return "苹果"
			} else {
				return "其他"
			}
		},
		"IntToStr": func(i int64) string {
			if i == 1 {
				return "是"
			} else {
				return "否"
			}
		},
		"BoolToInt": func(i bool) int {
			if i {
				return 1
			} else {
				return 0
			}
		},
		"SexToStr": func(i int) string {
			if i == 1 {
				return "男"
			} else {
				return "女"
			}
		},
		"ArrToStr": func(ia []int) string {
			var arr []string
			for i := 0; i < len(ia); i++ {
				arr = append(arr, strconv.Itoa(ia[i]))
			}
			return strings.Join(arr, ",")
		},
		"PermissionToStr": func(n int64) string {
			ret := ""
			p := models.GetPermissions()
			for i := 0; i < len(p); i++ {
				if (n & (1 << uint(p[i].Id))) != 0 {
					if ret == "" {
						ret = p[i].Name
					} else {
						ret = ret + " | " + p[i].Name
					}
				}
			}

			return ret
		},
	}
	beego.AddTemplateEngine("ace", func(root, path string, funcs template.FuncMap) (*template.Template, error) {
		aceOptions := &ace.Options{DynamicReload: true, FuncMap: funcMap}
		aceBasePath := filepath.Join(root, "base")
		aceInnerPath := filepath.Join(root, strings.TrimSuffix(path, ".ace"))
		tpl, err := ace.Load(aceBasePath, aceInnerPath, aceOptions)
		if err != nil {
			return nil, fmt.Errorf("error loading ace template: %v", err)
		}
		return tpl, nil
	})
}

func main() {
	if len(os.Args) > 1 && os.Args[1] == "init" {
		initDb()
		return
	}
	if len(os.Args) > 1 && os.Args[1] == "patch" {
		patchDb()
		return
	}

	ioutil.WriteFile("./goadmin.pid", []byte(strconv.Itoa(os.Getpid())), 0666)

	// 注册sqlite
	orm.RegisterDriver("sqlite3", orm.DRSqlite)
	orm.RegisterDataBase("default", "sqlite3", dsn)
	orm.RegisterDataBase("admin", "sqlite3", dsn)

	//模板初始化
	addAceTemplate()

	beego.SetLevel(beego.LevelInformational)
	beego.Run()
}

func initDb() {
	os.Remove(dsn)

	orm.RegisterDriver("sqlite3", orm.DRSqlite)
	orm.RegisterDataBase("default", "sqlite3", dsn)
	orm.RegisterDataBase("admin", "sqlite3", dsn)

	db, err := sql.Open("sqlite3", dsn)
	if err != nil {
		panic(err.Error())
	}
	r, err := db.Exec("create table init (n varchar(32));drop table init;")
	if err != nil {
		log.Println(err)
		log.Println(r)
	} else {
		log.Println("Database ", " created")
	}

	o := orm.NewOrm()
	o.Using("admin")
	orm.RunSyncdb("admin", true, true)

	u := new(models.User)
	u.Username = "admin"
	u.Role = 1
	u.Password = models.Strtomd5("admin123")
	u.CreateTs = time.Now().Unix()
	u.LastLoginTs = time.Now().Unix()
	o.Insert(u)

	role := new(models.Role)
	role.Name = "管理员"
	role.Permission = 0xFFFFFFFF
	o.Insert(role)
}

func patchDb() {
	orm.RegisterDriver("sqlite3", orm.DRSqlite)
	orm.RegisterDataBase("default", "sqlite3", dsn)
	orm.RegisterDataBase("admin", "sqlite3", dsn)

	//force - drop table 后再建表
	orm.RunSyncdb("admin", false, true)

	// o := orm.NewOrm()
	// o.Insert(&models.SystemParameter{Key: "test_server", Value: ""})
	// o.Insert(&models.SystemParameter{Key: "game_server", Value: ""})
}
